package com.learn.excel.core.aop;

import com.alibaba.fastjson.JSON;
import com.learn.excel.core.util.IpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 请求参数拦截
 *
 * @author:杜海强
 */
@Slf4j
@Aspect
@Component
public class ControllerAop {

    @Pointcut("execution(public * com.learn.excel.api.*.*.*(..))")
    public void apiPointcut() {
    }

    @Before("apiPointcut()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest req = attributes.getRequest();
        String requestUrl = req.getRequestURL().toString();
        requestUrl = requestUrl.substring(requestUrl.indexOf("http://") + 7);
        requestUrl = requestUrl.substring(requestUrl.indexOf("/"));
        log.debug("aop before: 请求地址: " + requestUrl);
        Object[] args = excludeJoinPointArgs(joinPoint);
        String ip = IpUtils.getIpAddr(req);
        log.debug("aop before: 请求方IP: " + ip);
        log.debug("aop before: 请求参数: {} ", JSON.toJSONString(args));
    }

    @AfterReturning(pointcut = "apiPointcut()", returning = "ret")
    public void doAfterReturning(Object ret) throws Throwable {
        log.debug("aop after: 方法返回值 : " + ret);
    }

    /**
     * 排除ServletRequest 和 ServletResponse
     */
    private Object[] excludeJoinPointArgs(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        Stream<?> stream = ArrayUtils.isEmpty(args) ? Stream.empty() : Arrays.asList(args).stream();
        List<Object> logArgs = stream.filter(arg -> (!(arg instanceof ServletRequest)
                && !(arg instanceof ServletResponse)
                && !(arg instanceof MultipartFile)
                && !(arg instanceof MultipartFile[]))).collect(Collectors.toList());
        if (logArgs.isEmpty()) {
            return null;
        }
        return logArgs.toArray();
    }

}
